home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / viper / viper-ex.el.z / viper-ex.el
Encoding:
Text File  |  1998-05-21  |  70.1 KB  |  2,192 lines

  1. ;;; viper-ex.el --- functions implementing the Ex commands for Viper
  2.  
  3. ;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
  4.  
  5. ;; This file is part of GNU Emacs.
  6.  
  7. ;; GNU Emacs is free software; you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation; either version 2, or (at your option)
  10. ;; any later version.
  11.  
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ;; GNU General Public License for more details.
  16.  
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  19. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20. ;; Boston, MA 02111-1307, USA.
  21.  
  22. ;; Code
  23.  
  24. (provide 'viper-ex)
  25.  
  26. ;; Compiler pacifier
  27. (defvar read-file-name-map)
  28. (defvar viper-use-register)
  29. (defvar viper-s-string)
  30. (defvar viper-shift-width)
  31. (defvar viper-ex-history)
  32. (defvar viper-related-files-and-buffers-ring)
  33. (defvar viper-local-search-start-marker)
  34. (defvar viper-expert-level)
  35. (defvar viper-custom-file-name)
  36. (defvar viper-case-fold-search)
  37. (defvar explicit-shell-file-name)
  38.  
  39. ;; loading happens only in non-interactive compilation
  40. ;; in order to spare non-viperized emacs from being viperized
  41. (if noninteractive
  42.     (eval-when-compile
  43.       (let ((load-path (cons (expand-file-name ".") load-path)))
  44.     (or (featurep 'viper-util)
  45.         (load "viper-util.el" nil nil 'nosuffix))
  46.     (or (featurep 'viper-keym)
  47.         (load "viper-keym.el" nil nil 'nosuffix))
  48.     (or (featurep 'viper-cmd)
  49.         (load "viper-cmd.el" nil nil 'nosuffix))
  50.     )))
  51. ;; end pacifier
  52.  
  53. (require 'viper-util)
  54.  
  55. (defgroup viper-ex nil
  56.   "Viper support for Ex commands"
  57.   :prefix "ex-"
  58.   :group 'viper)
  59.  
  60.  
  61.  
  62. ;;; Variables
  63.  
  64. (defconst viper-ex-work-buf-name " *ex-working-space*")
  65. (defconst viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name))
  66. (defconst viper-ex-tmp-buf-name " *ex-tmp*")
  67.  
  68.  
  69. ;;; Variable completion in :set command
  70.   
  71. ;; The list of Ex commands. Used for completing command names.
  72. (defconst ex-token-alist
  73.   '(("!") ("=") (">") ("&") ("~")
  74.     ("yank") ("xit") ("WWrite") ("Write") ("write") ("wq") ("visual") 
  75.     ("version") ("vglobal") ("unmap") ("undo") ("tag") ("transfer") ("suspend")
  76.     ("substitute") ("submitReport") ("stop")  ("sr") ("source") ("shell")
  77.     ("set") ("rewind") ("recover") ("read") ("quit") ("pwd")
  78.     ("put") ("preserve") ("PreviousRelatedFile") ("RelatedFile")
  79.     ("next") ("Next") ("move") ("mark") ("map") ("kmark") ("join")
  80.     ("help") ("goto") ("global") ("file") ("edit") ("delete") ("copy")
  81.     ("chdir") ("cd") ("Buffer") ("buffer") ("args"))  )
  82.  
  83. ;; A-list of Ex variables that can be set using the :set command.
  84. (defconst ex-variable-alist 
  85.   '(("wrapscan") ("ws") ("wrapmargin") ("wm")
  86.     ("tabstop-global") ("ts-g") ("tabstop") ("ts")
  87.     ("showmatch") ("sm") ("shiftwidth") ("sw") ("shell") ("sh")
  88.     ("readonly") ("ro") 
  89.     ("nowrapscan") ("nows") ("noshowmatch") ("nosm")
  90.     ("noreadonly") ("noro") ("nomagic") ("noma")
  91.     ("noignorecase") ("noic")
  92.     ("noautoindent-global") ("noai-g") ("noautoindent") ("noai")
  93.     ("magic") ("ma") ("ignorecase") ("ic")
  94.     ("autoindent-global") ("ai-g") ("autoindent") ("ai") 
  95.     ("all") 
  96.     ))
  97.  
  98.   
  99.  
  100. ;; Token recognized during parsing of Ex commands (e.g., "read", "comma")
  101. (defvar ex-token nil)
  102.  
  103. ;; Type of token. 
  104. ;; If non-nil, gives type of address; if nil, it is a command.
  105. (defvar ex-token-type nil)
  106.  
  107. ;; List of addresses passed to Ex command
  108. (defvar ex-addresses nil)
  109.  
  110. ;; This flag is supposed to be set only by `#', `print', and `list',
  111. ;; none of which is implemented. So, it and the pices of the code it
  112. ;; controls are dead weight. We keep it just in case this might be
  113. ;; needed in the future.
  114. (defvar ex-flag nil)
  115.  
  116. ;; "buffer" where Ex commands keep deleted data.
  117. ;; In Emacs terms, this is a register.
  118. (defvar ex-buffer nil)
  119.  
  120. ;; Value of ex count.
  121. (defvar ex-count nil)
  122.  
  123. ;; Flag indicating that :global Ex command is being executed.
  124. (defvar ex-g-flag nil)
  125. ;; Flag indicating that :vglobal Ex command is being executed.
  126. (defvar ex-g-variant nil)
  127.  
  128. ;; Save reg-exp used in substitute.
  129. (defvar ex-reg-exp nil)
  130.  
  131.  
  132. ;; Replace pattern for substitute.
  133. (defvar ex-repl nil)
  134.  
  135. ;; Pattern for global command.
  136. (defvar ex-g-pat nil)
  137.  
  138. (defcustom ex-unix-type-shell
  139.   (let ((case-fold-search t))
  140.     (and (stringp shell-file-name)
  141.      (string-match
  142.       (concat
  143.        "\\("
  144.        "csh$\\|csh.exe$"
  145.        "\\|"
  146.        "ksh$\\|ksh.exe$"
  147.        "\\|"
  148.        "^sh$\\|sh.exe$"
  149.        "\\|"
  150.        "[^a-z]sh$\\|[^a-z]sh.exe$"
  151.        "\\|"
  152.        "bash$\\|bash.exe$"
  153.        "\\)")
  154.       shell-file-name)))
  155.   "Is the user using a unix-type shell under a non-OS?"
  156.   :type 'boolean
  157.   :group 'viper-ex)
  158.  
  159. (defcustom ex-unix-type-shell-options
  160.   (let ((case-fold-search t))
  161.     (if ex-unix-type-shell
  162.     (cond ((string-match "\\(csh$\\|csh.exe$\\)" shell-file-name)
  163.            "-f") ; csh: do it fast
  164.           ((string-match "\\(bash$\\|bash.exe$\\)" shell-file-name)
  165.            "-noprofile") ; bash: ignore .profile
  166.           )))
  167.   "Options to pass to the Unix-style shell. 
  168. Don't put `-c' here, as it is added automatically."
  169.   :type 'string
  170.   :group 'viper-ex)
  171.  
  172. (defvar ex-nontrivial-find-file-function
  173.   (cond (ex-unix-type-shell 'viper-ex-nontrivial-find-file-unix)
  174.     ((eq system-type 'emx) 'viper-ex-nontrivial-find-file-ms) ; OS/2
  175.     (viper-ms-style-os-p 'viper-ex-nontrivial-find-file-ms) ; Microsoft OS
  176.     (viper-vms-os-p 'viper-ex-nontrivial-find-file-unix) ; VMS
  177.     (t  'viper-ex-nontrivial-find-file-unix) ; presumably UNIX
  178.     ))
  179.  
  180. ;; Remembers the previous Ex tag.
  181. (defvar ex-tag nil)
  182.  
  183. ;; file used by Ex commands like :r, :w, :n
  184. (defvar ex-file nil)
  185.  
  186. ;; If t, tells Ex that this is a variant-command, i.e., w>>, r!, etc.
  187. (defvar ex-variant nil)
  188.  
  189. ;; Specified the offset of an Ex command, such as :read.
  190. (defvar ex-offset nil)
  191.  
  192. ;; Tells Ex that this is a w>> command.
  193. (defvar ex-append nil)
  194.  
  195. ;; File containing the shell command to be executed at Ex prompt,
  196. ;; e.g., :r !date
  197. (defvar ex-cmdfile nil)
  198. (defvar ex-cmdfile-args "")
  199.   
  200. ;; flag used in viper-ex-read-file-name to indicate that we may be reading
  201. ;; multiple file names. Used for :edit and :next
  202. (defvar viper-keep-reading-filename nil)
  203.  
  204. (defcustom ex-cycle-other-window t
  205.   "*If t, :n and :b cycles through files and buffers in other window.
  206. Then :N and :B cycles in the current window. If nil, this behavior is
  207. reversed."
  208.   :type 'boolean
  209.   :group 'viper-ex)
  210.  
  211. (defcustom ex-cycle-through-non-files nil
  212.   "*Cycle through *scratch* and other buffers that don't visit any file."
  213.   :type 'boolean
  214.   :group 'viper-ex)
  215.  
  216. ;; Last shell command executed with :! command.
  217. (defvar viper-ex-last-shell-com nil)
  218.   
  219. ;; Indicates if Minibuffer was exited temporarily in Ex-command.
  220. (defvar viper-incomplete-ex-cmd nil)
  221.   
  222. ;; Remembers the last ex-command prompt.
  223. (defvar viper-last-ex-prompt "")
  224.  
  225.  
  226. ;;; Code
  227.   
  228. ;; Check if ex-token is an initial segment of STR
  229. (defun viper-check-sub (str)
  230.   (let ((length (length ex-token)))
  231.     (if (and (<= length (length str))
  232.            (string= ex-token (substring str 0 length)))
  233.     (setq ex-token str)
  234.       (setq ex-token-type 'non-command))))
  235.  
  236. ;; Get a complete ex command
  237. (defun viper-get-ex-com-subr ()
  238.   (let (case-fold-search)
  239.     (set-mark (point))
  240.     (re-search-forward "[a-zA-Z][a-zA-Z]*")
  241.     (setq ex-token-type 'command)
  242.     (setq ex-token (buffer-substring (point) (mark t)))
  243.     (exchange-point-and-mark)
  244.     (cond ((looking-at "a")
  245.        (cond ((looking-at "ab") (viper-check-sub "abbreviate"))
  246.          ((looking-at "ar") (viper-check-sub "args"))
  247.          (t (viper-check-sub "append"))))
  248.       ((looking-at "h") (viper-check-sub "help"))
  249.       ((looking-at "c")
  250.        (cond ((looking-at "cd") (viper-check-sub "cd"))
  251.          ((looking-at "ch") (viper-check-sub "chdir"))
  252.          ((looking-at "co") (viper-check-sub "copy"))
  253.          (t (viper-check-sub "change"))))
  254.       ((looking-at "d") (viper-check-sub "delete"))
  255.       ((looking-at "b") (viper-check-sub "buffer"))
  256.       ((looking-at "B") (viper-check-sub "Buffer"))
  257.       ((looking-at "e")
  258.        (if (looking-at "ex") (viper-check-sub "ex")
  259.          (viper-check-sub "edit")))
  260.       ((looking-at "f") (viper-check-sub "file"))
  261.       ((looking-at "g") (viper-check-sub "global"))
  262.       ((looking-at "i") (viper-check-sub "insert"))
  263.       ((looking-at "j") (viper-check-sub "join"))
  264.       ((looking-at "l") (viper-check-sub "list"))
  265.       ((looking-at "m")
  266.        (cond ((looking-at "map") (viper-check-sub "map"))
  267.          ((looking-at "mar") (viper-check-sub "mark"))
  268.          (t (viper-check-sub "move"))))
  269.       ((looking-at "k[a-z][^a-z]")
  270.        (setq ex-token "kmark")
  271.        (forward-char 1)
  272.        (exchange-point-and-mark))   ; this is canceled out by another
  273.                     ; exchange-point-and-mark at the end
  274.       ((looking-at "k") (viper-check-sub "kmark"))
  275.       ((looking-at "n") (if (looking-at "nu")
  276.                 (viper-check-sub "number")
  277.                   (viper-check-sub "next")))
  278.       ((looking-at "N") (viper-check-sub "Next"))
  279.       ((looking-at "o") (viper-check-sub "open"))
  280.       ((looking-at "p")
  281.        (cond ((looking-at "pre") (viper-check-sub "preserve"))
  282.          ((looking-at "pu") (viper-check-sub "put"))
  283.          ((looking-at "pw") (viper-check-sub "pwd"))
  284.          (t (viper-check-sub "print"))))
  285.       ((looking-at "P") (viper-check-sub "PreviousRelatedFile"))
  286.       ((looking-at "R") (viper-check-sub "RelatedFile"))
  287.       ((looking-at "q") (viper-check-sub "quit"))
  288.       ((looking-at "r")
  289.        (cond ((looking-at "rec") (viper-check-sub "recover"))
  290.          ((looking-at "rew") (viper-check-sub "rewind"))
  291.          (t (viper-check-sub "read"))))
  292.       ((looking-at "s")
  293.        (cond ((looking-at "se") (viper-check-sub "set"))
  294.          ((looking-at "sh") (viper-check-sub "shell"))
  295.          ((looking-at "so") (viper-check-sub "source"))
  296.          ((looking-at "sr") (viper-check-sub "sr"))
  297.          ((looking-at "st") (viper-check-sub "stop"))
  298.          ((looking-at "sus") (viper-check-sub "suspend"))
  299.          ((looking-at "subm") (viper-check-sub "submitReport"))
  300.          (t (viper-check-sub "substitute"))))
  301.       ((looking-at "t")
  302.        (if (looking-at "ta") (viper-check-sub "tag")
  303.          (viper-check-sub "transfer")))
  304.       ((looking-at "u")
  305.        (cond ((looking-at "una") (viper-check-sub "unabbreviate"))
  306.          ((looking-at "unm") (viper-check-sub "unmap"))
  307.          (t (viper-check-sub "undo"))))
  308.       ((looking-at "v")
  309.        (cond ((looking-at "ve") (viper-check-sub "version"))
  310.          ((looking-at "vi") (viper-check-sub "visual"))
  311.          (t (viper-check-sub "vglobal"))))
  312.       ((looking-at "w")
  313.        (if (looking-at "wq") (viper-check-sub "wq")
  314.          (viper-check-sub "write")))
  315.       ((looking-at "W")
  316.        (if (looking-at "WW") 
  317.            (viper-check-sub "WWrite")
  318.          (viper-check-sub "Write")))
  319.       ((looking-at "x") (viper-check-sub "xit"))
  320.       ((looking-at "y") (viper-check-sub "yank"))
  321.       ((looking-at "z") (viper-check-sub "z")))
  322.     (exchange-point-and-mark)
  323.     ))
  324.  
  325. ;; Get an ex-token which is either an address or a command.
  326. ;; A token has a type, \(command, address, end-mark\), and a value
  327. (defun viper-get-ex-token ()
  328.   (save-window-excursion
  329.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  330.     (set-buffer viper-ex-work-buf)
  331.     (skip-chars-forward " \t|")
  332.     (let ((case-fold-search t))
  333.       (cond ((looking-at "#")
  334.          (setq ex-token-type 'command)
  335.          (setq ex-token (char-to-string (following-char)))
  336.          (forward-char 1))
  337.         ((looking-at "[a-z]") (viper-get-ex-com-subr))
  338.         ((looking-at "\\.")
  339.          (forward-char 1)
  340.          (setq ex-token-type 'dot))
  341.         ((looking-at "[0-9]")
  342.          (set-mark (point))
  343.          (re-search-forward "[0-9]*")
  344.          (setq ex-token-type
  345.            (cond ((eq ex-token-type 'plus) 'add-number)
  346.              ((eq ex-token-type 'minus) 'sub-number)
  347.              (t 'abs-number)))
  348.          (setq ex-token
  349.            (string-to-int (buffer-substring (point) (mark t)))))
  350.         ((looking-at "\\$")
  351.          (forward-char 1)
  352.          (setq ex-token-type 'end))
  353.         ((looking-at "%")
  354.          (forward-char 1)
  355.          (setq ex-token-type 'whole))
  356.         ((looking-at "+")
  357.          (cond ((or (looking-at "+[-+]") (looking-at "+[\n|]"))
  358.             (forward-char 1)
  359.             (insert "1")
  360.             (backward-char 1)
  361.           (setq ex-token-type 'plus))
  362.            ((looking-at "+[0-9]")
  363.             (forward-char 1)
  364.             (setq ex-token-type 'plus))
  365.            (t
  366.             (error viper-BadAddress))))
  367.         ((looking-at "-")
  368.          (cond ((or (looking-at "-[-+]") (looking-at "-[\n|]"))
  369.             (forward-char 1)
  370.             (insert "1")
  371.             (backward-char 1)
  372.             (setq ex-token-type 'minus))
  373.            ((looking-at "-[0-9]")
  374.             (forward-char 1)
  375.             (setq ex-token-type 'minus))
  376.            (t
  377.             (error viper-BadAddress))))
  378.         ((looking-at "/")
  379.          (forward-char 1)
  380.          (set-mark (point))
  381.          (let ((cont t))
  382.            (while (and (not (eolp)) cont)
  383.          ;;(re-search-forward "[^/]*/")
  384.          (re-search-forward "[^/]*\\(/\\|\n\\)")
  385.          (if (not (viper-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
  386.              (setq cont nil))))
  387.          (backward-char 1)
  388.          (setq ex-token (buffer-substring (point) (mark t)))
  389.          (if (looking-at "/") (forward-char 1))
  390.          (setq ex-token-type 'search-forward))
  391.         ((looking-at "\\?")
  392.          (forward-char 1)
  393.          (set-mark (point))
  394.          (let ((cont t))
  395.            (while (and (not (eolp)) cont)
  396.          ;;(re-search-forward "[^\\?]*\\?")
  397.          (re-search-forward "[^\\?]*\\(\\?\\|\n\\)")
  398.          (if (not (viper-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\\\?"))
  399.              (setq cont nil))
  400.          (backward-char 1)
  401.          (if (not (looking-at "\n")) (forward-char 1))))
  402.          (setq ex-token-type 'search-backward)
  403.          (setq ex-token (buffer-substring (1- (point)) (mark t))))
  404.         ((looking-at ",")
  405.          (forward-char 1)
  406.          (setq ex-token-type 'comma))
  407.         ((looking-at ";")
  408.          (forward-char 1)
  409.          (setq ex-token-type 'semi-colon))
  410.         ((looking-at "[!=><&~]")
  411.          (setq ex-token-type 'command)
  412.          (setq ex-token (char-to-string (following-char)))
  413.          (forward-char 1))
  414.         ((looking-at "'")
  415.          (setq ex-token-type 'goto-mark)
  416.          (forward-char 1)
  417.          (cond ((looking-at "'") (setq ex-token nil))
  418.            ((looking-at "[a-z]") (setq ex-token (following-char)))
  419.            (t (error "Marks are ' and a-z")))
  420.          (forward-char 1))
  421.         ((looking-at "\n")
  422.          (setq ex-token-type 'end-mark)
  423.          (setq ex-token "goto"))
  424.         (t
  425.          (error viper-BadExCommand))))))
  426.  
  427. ;; Reads Ex command. Tries to determine if it has to exit because command
  428. ;; is complete or invalid. If not, keeps reading command.
  429. (defun ex-cmd-read-exit ()
  430.   (interactive)
  431.   (setq viper-incomplete-ex-cmd t)
  432.   (let ((quit-regex1 (concat
  433.               "\\(" "set[ \t]*"
  434.               "\\|" "edit[ \t]*"
  435.               "\\|" "[nN]ext[ \t]*"
  436.               "\\|" "unm[ \t]*"
  437.               "\\|" "^[ \t]*rep"
  438.               "\\)"))
  439.     (quit-regex2 (concat
  440.               "[a-zA-Z][ \t]*"
  441.               "\\(" "!" "\\|" ">>"
  442.               "\\|" "\\+[0-9]+"
  443.               "\\)"
  444.               "*[ \t]*$"))
  445.     (stay-regex (concat
  446.              "\\(" "^[ \t]*$"
  447.              "\\|" "[?/].*"
  448.              "\\|" "[ktgjmsz][ \t]*$"
  449.              "\\|" "^[ \t]*ab.*"
  450.              "\\|" "tr[ansfer \t]*"
  451.              "\\|" "sr[ \t]*"
  452.              "\\|" "mo.*"
  453.              "\\|" "^[ \t]*k?ma[^p]*"
  454.              "\\|" "^[ \t]*fi.*"
  455.              "\\|" "v?gl.*"
  456.              "\\|" "[vg][ \t]*$"
  457.              "\\|" "jo.*"
  458.              "\\|" "^[ \t]*ta.*"
  459.              "\\|" "^[ \t]*una.*"
  460.              "\\|" "^[ \t]*su.*"
  461.              "\\|" "['`][a-z][ \t]*"
  462.              ;; r! assumes that the next one is a shell command
  463.              "\\|" "\\(r\\|re\\|rea\\|read\\)[ \t]*!"
  464.              ;; w ! assumes that the next one is a shell command
  465.              "\\|" "\\(w\\|wr\\|wri\\|writ.?\\)[ \t]+!"
  466.              "\\|" "![ \t]*[a-zA-Z].*"
  467.              "\\)"
  468.              "!*")))
  469.     
  470.     (save-window-excursion ;; put cursor at the end of the Ex working buffer
  471.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  472.       (set-buffer viper-ex-work-buf)
  473.       (goto-char (point-max)))
  474.     (cond ((viper-looking-back quit-regex1) (exit-minibuffer))
  475.       ((viper-looking-back stay-regex)  (insert " "))
  476.       ((viper-looking-back quit-regex2) (exit-minibuffer))
  477.       (t (insert " ")))))
  478.   
  479. ;; complete Ex command
  480. (defun ex-cmd-complete ()
  481.   (interactive)
  482.   (let (save-pos dist compl-list string-to-complete completion-result)
  483.     
  484.     (save-excursion
  485.       (setq dist (skip-chars-backward "[a-zA-Z!=>&~]")
  486.         save-pos (point)))
  487.     
  488.     (if (or (= dist 0)
  489.         (viper-looking-back "\\([ \t]*['`][ \t]*[a-z]*\\)")
  490.         (viper-looking-back
  491.          "^[ \t]*[a-zA-Z!=>&~][ \t]*[/?]*+[ \t]+[a-zA-Z!=>&~]+"))
  492.     ;; Preceding characters are not the ones allowed in an Ex command
  493.     ;; or we have typed past command name.
  494.     ;; Note: we didn't do parsing, so there may be surprises.
  495.     (if (or (viper-looking-back "[a-zA-Z!=>&~][ \t]*[/?]*[ \t]*")
  496.         (viper-looking-back "\\([ \t]*['`][ \t]*[a-z]*\\)")
  497.         (looking-at "[^ \t\n\C-m]"))
  498.         nil
  499.       (with-output-to-temp-buffer "*Completions*" 
  500.         (display-completion-list
  501.          (viper-alist-to-list ex-token-alist))))
  502.       ;; Preceding chars may be part of a command name
  503.       (setq string-to-complete (buffer-substring save-pos (point)))
  504.       (setq completion-result
  505.         (try-completion string-to-complete ex-token-alist))
  506.       
  507.       (cond ((eq completion-result t)  ; exact match--do nothing
  508.          (viper-tmp-insert-at-eob " (Sole completion)"))
  509.         ((eq completion-result nil)
  510.          (viper-tmp-insert-at-eob " (No match)"))
  511.         (t  ;; partial completion
  512.          (goto-char save-pos)
  513.          (delete-region (point) (point-max))
  514.          (insert completion-result)
  515.          (let (case-fold-search)
  516.            (setq compl-list
  517.              (viper-filter-alist (concat "^" completion-result)
  518.                        ex-token-alist)))
  519.          (if (> (length compl-list) 1)
  520.          (with-output-to-temp-buffer "*Completions*" 
  521.            (display-completion-list
  522.             (viper-alist-to-list (reverse compl-list)))))))
  523.       )))
  524.     
  525.  
  526. ;; Read Ex commands 
  527. (defun viper-ex (arg &optional string)
  528.   (interactive "P")
  529.   (or string
  530.       (setq ex-g-flag nil
  531.         ex-g-variant nil))
  532.   (let* ((map (copy-keymap minibuffer-local-map))
  533.      (address nil)
  534.      (cont t)
  535.      (dot (point))
  536.      reg-beg-line reg-end-line
  537.      reg-beg reg-end
  538.      initial-str
  539.      prev-token-type com-str)
  540.     (viper-add-keymap viper-ex-cmd-map map)
  541.  
  542.     (if arg
  543.     (progn
  544.       (viper-enlarge-region (mark t) (point))
  545.       (if (> (point) (mark t))
  546.           (setq reg-beg (mark t)
  547.             reg-end (point))
  548.         (setq reg-end (mark t)
  549.           reg-beg (point)))
  550.       (save-excursion
  551.         (goto-char reg-beg)
  552.         (setq reg-beg-line (1+ (count-lines (point-min) (point)))
  553.           reg-end-line
  554.           (+ reg-beg-line (count-lines reg-beg reg-end) -1)))))
  555.     (if reg-beg-line
  556.     (setq initial-str (format "%d,%d" reg-beg-line reg-end-line)))
  557.     
  558.     (setq com-str 
  559.       (or string (viper-read-string-with-history
  560.               ":" 
  561.               initial-str
  562.               'viper-ex-history
  563.               ;; no default when working on region
  564.               (if initial-str
  565.               "none"
  566.             (car viper-ex-history))
  567.               map
  568.               (if initial-str
  569.               " [Type command to execute on current region]"))))
  570.     (save-window-excursion
  571.       ;; just a precaution
  572.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  573.       (set-buffer viper-ex-work-buf)
  574.       (delete-region (point-min) (point-max))
  575.       (insert com-str "\n")
  576.       (goto-char (point-min)))
  577.     (setq ex-token-type nil
  578.       ex-addresses nil)
  579.     (while cont
  580.       (viper-get-ex-token)
  581.       (cond ((memq ex-token-type '(command end-mark))
  582.          (if address (setq ex-addresses (cons address ex-addresses)))
  583.          (cond ((string= ex-token "global")
  584.             (ex-global nil)
  585.             (setq cont nil))
  586.            ((string= ex-token "vglobal")
  587.             (ex-global t)
  588.             (setq cont nil))
  589.            (t
  590.             (viper-execute-ex-command)
  591.             (save-window-excursion
  592.               (setq viper-ex-work-buf
  593.                 (get-buffer-create viper-ex-work-buf-name))
  594.               (set-buffer viper-ex-work-buf)
  595.               (skip-chars-forward " \t")
  596.               (cond ((looking-at "|")
  597.                  (forward-char 1))
  598.                 ((looking-at "\n")
  599.                  (setq cont nil))
  600.                 (t (error "`%s': %s" ex-token viper-SpuriousText)))
  601.               ))
  602.            ))
  603.         ((eq ex-token-type 'non-command)
  604.          (error "`%s': %s" ex-token viper-BadExCommand))
  605.         ((eq ex-token-type 'whole)
  606.          (setq address nil)
  607.          (setq ex-addresses
  608.            (if ex-addresses
  609.                (cons (point-max) ex-addresses)
  610.              (cons (point-max) (cons (point-min) ex-addresses)))))
  611.         ((eq ex-token-type 'comma)
  612.          (if (eq prev-token-type 'whole)
  613.          (setq address (point-min)))
  614.          (setq ex-addresses
  615.            (cons (if (null address) (point) address) ex-addresses)))
  616.         ((eq ex-token-type 'semi-colon)
  617.          (if (eq prev-token-type 'whole)
  618.          (setq address (point-min)))
  619.          (if address (setq dot address))
  620.          (setq ex-addresses
  621.            (cons (if (null address) (point) address) ex-addresses)))
  622.         (t (let ((ans (viper-get-ex-address-subr address dot)))
  623.          (if ans (setq address ans)))))
  624.       (setq prev-token-type ex-token-type))))
  625.       
  626.  
  627. ;; Get a regular expression and set `ex-variant', if found
  628. (defun viper-get-ex-pat ()
  629.   (save-window-excursion
  630.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name))
  631.     (set-buffer viper-ex-work-buf)
  632.     (skip-chars-forward " \t")
  633.     (if (looking-at "!")
  634.     (progn
  635.       (setq ex-g-variant (not ex-g-variant)
  636.         ex-g-flag (not ex-g-flag))
  637.       (forward-char 1)
  638.       (skip-chars-forward " \t")))
  639.     (let ((c (following-char)))
  640.       (if (string-match "[0-9A-Za-z]" (format "%c" c))
  641.       (error
  642.        "Global regexp must be inside matching non-alphanumeric chars"))
  643.       (if (looking-at "[^\\\\\n]")
  644.       (progn
  645.         (forward-char 1)
  646.         (set-mark (point))
  647.         (let ((cont t))
  648.           (while (and (not (eolp)) cont)
  649.         (if (not (re-search-forward (format "[^%c]*%c" c c) nil t))
  650.             (if (member ex-token '("global" "vglobal"))
  651.             (error
  652.              "Missing closing delimiter for global regexp")
  653.               (goto-char (point-max))))
  654.         (if (not (viper-looking-back
  655.               (format "[^\\\\]\\(\\\\\\\\\\)*\\\\%c" c)))
  656.             (setq cont nil))))
  657.         (setq ex-token
  658.           (if (= (mark t) (point)) ""
  659.             (buffer-substring (1- (point)) (mark t))))
  660.         (backward-char 1)
  661.         ;; if the user doesn't specify the final pattern delimiter, we're
  662.         ;; at newline now. In this case, insert the initial delimiter
  663.         ;; specified in variable c
  664.         (if (looking-at "\n")
  665.         (progn
  666.             (insert c)
  667.               (backward-char 1)))
  668.         )
  669.     (setq ex-token nil))
  670.       c)))
  671.  
  672. ;; get an ex command
  673. (defun viper-get-ex-command ()
  674.   (save-window-excursion
  675.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  676.     (set-buffer viper-ex-work-buf)
  677.     (if (looking-at "/") (forward-char 1))
  678.     (skip-chars-forward " \t")
  679.     (cond ((looking-at "[a-z]")
  680.        (viper-get-ex-com-subr)
  681.        (if (eq ex-token-type 'non-command)
  682.            (error "`%s': %s" ex-token viper-BadExCommand)))
  683.       ((looking-at "[!=><&~]")
  684.        (setq ex-token (char-to-string (following-char)))
  685.        (forward-char 1))
  686.       (t (error viper-BadExCommand)))))
  687.  
  688. ;; Get an Ex option g or c
  689. (defun viper-get-ex-opt-gc (c)
  690.   (save-window-excursion
  691.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  692.     (set-buffer viper-ex-work-buf)
  693.     (if (looking-at (format "%c" c)) (forward-char 1))
  694.     (skip-chars-forward " \t")
  695.     (cond ((looking-at "g")
  696.        (setq ex-token "g")
  697.        (forward-char 1)
  698.        t)
  699.       ((looking-at "c")
  700.        (setq ex-token "c")
  701.        (forward-char 1)
  702.        t)
  703.       (t nil))))
  704.  
  705. ;; Compute default addresses.  WHOLE-FLAG means use the whole buffer
  706. (defun viper-default-ex-addresses (&optional whole-flag)
  707.   (cond ((null ex-addresses)
  708.      (setq ex-addresses
  709.            (if whole-flag
  710.            (cons (point-max) (cons (point-min) nil))
  711.          (cons (point) (cons (point) nil)))))
  712.     ((null (cdr ex-addresses))
  713.      (setq ex-addresses
  714.            (cons (car ex-addresses) ex-addresses)))))
  715.  
  716. ;; Get an ex-address as a marker and set ex-flag if a flag is found
  717. (defun viper-get-ex-address ()
  718.   (let ((address (point-marker))
  719.     (cont t))
  720.     (setq ex-token "")
  721.     (setq ex-flag nil)
  722.     (while cont
  723.       (viper-get-ex-token)
  724.       (cond ((eq ex-token-type 'command)
  725.          (if (member ex-token '("print" "list" "#"))
  726.          (progn
  727.            (setq ex-flag t
  728.              cont nil))
  729.            (error "Address expected in this Ex command")))
  730.         ((eq ex-token-type 'end-mark)
  731.          (setq cont nil))
  732.         ((eq ex-token-type 'whole)
  733.          (error "Trailing address expected"))
  734.         ((eq ex-token-type 'comma)
  735.          (error "`%s': %s" ex-token viper-SpuriousText))
  736.         (t (let ((ans (viper-get-ex-address-subr address (point-marker))))
  737.          (if ans (setq address ans))))))
  738.     address))
  739.  
  740. ;; Returns an address as a point
  741. (defun viper-get-ex-address-subr (old-address dot)
  742.   (let ((address nil))
  743.     (if (null old-address) (setq old-address dot))
  744.     (cond ((eq ex-token-type 'dot)
  745.        (setq address dot))
  746.       ((eq ex-token-type 'add-number)
  747.        (save-excursion
  748.          (goto-char old-address)
  749.          (forward-line (if (= old-address 0) (1- ex-token) ex-token))
  750.          (setq address (point-marker))))
  751.       ((eq ex-token-type 'sub-number)
  752.        (save-excursion
  753.          (goto-char old-address)
  754.          (forward-line (- ex-token))
  755.          (setq address (point-marker))))
  756.       ((eq ex-token-type 'abs-number)
  757.        (save-excursion
  758.          (goto-char (point-min))
  759.          (if (= ex-token 0) (setq address 0)
  760.            (forward-line (1- ex-token))
  761.            (setq address (point-marker)))))
  762.       ((eq ex-token-type 'end)
  763.        (setq address (point-max-marker)))
  764.       ((eq ex-token-type 'plus) t)  ; do nothing
  765.       ((eq ex-token-type 'minus) t) ; do nothing
  766.       ((eq ex-token-type 'search-forward)
  767.        (save-excursion
  768.          (ex-search-address t)
  769.          (setq address (point-marker))))
  770.       ((eq ex-token-type 'search-backward)
  771.        (save-excursion
  772.          (ex-search-address nil)
  773.          (setq address (point-marker))))
  774.       ((eq ex-token-type 'goto-mark)
  775.        (save-excursion
  776.          (if (null ex-token)
  777.          (exchange-point-and-mark)
  778.            (goto-char (viper-register-to-point
  779.                (1+ (- ex-token ?a)) 'enforce-buffer)))
  780.          (setq address (point-marker)))))
  781.     address))
  782.  
  783.  
  784. ;; Search pattern and set address
  785. (defun ex-search-address (forward)
  786.   (if (string= ex-token "")
  787.       (if (null viper-s-string)
  788.       (error viper-NoPrevSearch)
  789.     (setq ex-token viper-s-string))
  790.     (setq viper-s-string ex-token))
  791.   (if forward
  792.       (progn
  793.     (forward-line 1)
  794.     (re-search-forward ex-token))
  795.     (forward-line -1)
  796.     (re-search-backward ex-token)))
  797.  
  798. ;; Get a buffer name and set `ex-count' and `ex-flag' if found
  799. (defun viper-get-ex-buffer ()
  800.   (setq ex-buffer nil)
  801.   (setq ex-count nil)
  802.   (setq ex-flag nil)
  803.   (save-window-excursion
  804.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  805.     (set-buffer viper-ex-work-buf)
  806.     (skip-chars-forward " \t")
  807.     (if (looking-at "[a-zA-Z]")
  808.     (progn
  809.       (setq ex-buffer (following-char))
  810.       (forward-char 1)
  811.       (skip-chars-forward " \t")))
  812.     (if (looking-at "[0-9]")
  813.     (progn
  814.       (set-mark (point))
  815.       (re-search-forward "[0-9][0-9]*")
  816.       (setq ex-count (string-to-int (buffer-substring (point) (mark t))))
  817.       (skip-chars-forward " \t")))
  818.     (if (looking-at "[pl#]")
  819.     (progn
  820.       (setq ex-flag t)
  821.       (forward-char 1)))
  822.     (if (not (looking-at "[\n|]"))
  823.     (error "`%s': %s" ex-token viper-SpuriousText))))
  824.  
  825. (defun viper-get-ex-count ()
  826.   (setq ex-variant nil
  827.     ex-count nil
  828.     ex-flag nil)
  829.   (save-window-excursion
  830.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  831.     (set-buffer viper-ex-work-buf)
  832.     (skip-chars-forward " \t")
  833.     (if (looking-at "!")
  834.     (progn
  835.       (setq ex-variant t)
  836.       (forward-char 1)))
  837.     (skip-chars-forward " \t")
  838.     (if (looking-at "[0-9]")
  839.     (progn
  840.       (set-mark (point))
  841.       (re-search-forward "[0-9][0-9]*")
  842.       (setq ex-count (string-to-int (buffer-substring (point) (mark t))))
  843.       (skip-chars-forward " \t")))
  844.     (if (looking-at "[pl#]")
  845.     (progn
  846.       (setq ex-flag t)
  847.       (forward-char 1)))
  848.     (if (not (looking-at "[\n|]"))
  849.     (error "`%s': %s"
  850.            (buffer-substring
  851.         (point-min) (1- (point-max))) viper-BadExCommand))))
  852.  
  853. ;; Expand \% and \# in ex command
  854. (defun ex-expand-filsyms (cmd buf)
  855.   (let (cf pf ret)
  856.     (save-excursion 
  857.       (set-buffer buf)
  858.       (setq cf buffer-file-name)
  859.       (setq pf (ex-next nil t))) ; this finds alternative file name
  860.     (if (and (null cf) (string-match "[^\\]%\\|\\`%" cmd))
  861.     (error "No current file to substitute for `%%'"))
  862.     (if (and (null pf) (string-match "[^\\]#\\|\\`#" cmd))
  863.     (error "No alternate file to substitute for `#'"))
  864.     (save-excursion
  865.       (set-buffer (get-buffer-create viper-ex-tmp-buf-name))
  866.       (erase-buffer)
  867.       (insert cmd)
  868.       (goto-char (point-min))
  869.       (while (re-search-forward "%\\|#" nil t)
  870.     (let ((data (match-data)) 
  871.           (char (buffer-substring (match-beginning 0) (match-end 0))))
  872.       (if (viper-looking-back (concat "\\\\" char))
  873.           (replace-match char)
  874.         (store-match-data data)
  875.         (if (string= char "%")
  876.         (replace-match cf)
  877.           (replace-match pf)))))
  878.       (end-of-line)
  879.       (setq ret (buffer-substring (point-min) (point)))
  880.       (message "%s" ret))
  881.     ret))
  882.  
  883. ;; Get a file name and set `ex-variant', `ex-append' and `ex-offset' if found
  884. ;; If it is r!, then get the command name and whatever args
  885. (defun viper-get-ex-file ()
  886.   (let (prompt)
  887.     (setq ex-file nil
  888.       ex-variant nil
  889.       ex-append nil
  890.       ex-offset nil
  891.       ex-cmdfile nil
  892.       ex-cmdfile-args "")
  893.     (save-excursion
  894.       (save-window-excursion
  895.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  896.     (set-buffer viper-ex-work-buf)
  897.     (skip-chars-forward " \t")
  898.     (if (looking-at "!")
  899.         (if (and (not (viper-looking-back "[ \t]"))
  900.              ;; read doesn't have a corresponding :r! form, so ! is
  901.              ;; immediately interpreted as a shell command.
  902.              (not (string= ex-token "read")))
  903.         (progn
  904.           (setq ex-variant t)
  905.           (forward-char 1)
  906.           (skip-chars-forward " \t"))
  907.           (setq ex-cmdfile t)
  908.           (forward-char 1)
  909.           (skip-chars-forward " \t")))
  910.     (if (looking-at ">>")
  911.         (progn
  912.           (setq ex-append t
  913.             ex-variant t)
  914.           (forward-char 2)
  915.           (skip-chars-forward " \t")))
  916.     (if (looking-at "+")
  917.         (progn
  918.           (forward-char 1)
  919.           (set-mark (point))
  920.           (re-search-forward "[ \t\n]")
  921.           (backward-char 1)
  922.           (setq ex-offset (buffer-substring (point) (mark t)))
  923.           (forward-char 1)
  924.           (skip-chars-forward " \t")))
  925.     ;; this takes care of :r, :w, etc., when they get file names
  926.     ;; from the history list
  927.     (if (member ex-token '("read" "write" "edit" "visual" "next"))
  928.         (progn
  929.           (setq ex-file (buffer-substring (point)  (1- (point-max))))
  930.           (setq ex-file
  931.             ;; For :e, match multiple non-white strings separated
  932.             ;; by white. For others, find the first non-white string
  933.             (if (string-match
  934.              (if (string= ex-token "edit")
  935.                  "[^ \t\n]+\\([ \t]+[^ \t\n]+\\)*"
  936.                "[^ \t\n]+")
  937.              ex-file)
  938.             (progn
  939.               ;; if file name comes from history, don't leave
  940.               ;; minibuffer when the user types space
  941.               (setq viper-incomplete-ex-cmd nil)
  942.               (setq ex-cmdfile-args
  943.                 (substring ex-file (match-end 0) nil))
  944.               ;; this must be the last clause in this progn
  945.               (substring ex-file (match-beginning 0) (match-end 0))
  946.               )
  947.               ""))
  948.           ;; this leaves only the command name in the work area
  949.           ;; file names are gone
  950.           (delete-region (point) (1- (point-max)))
  951.           ))
  952.     (goto-char (point-max))
  953.     (skip-chars-backward " \t\n")
  954.     (setq prompt (buffer-substring (point-min) (point)))
  955.     ))
  956.     
  957.     (setq viper-last-ex-prompt prompt)
  958.     
  959.     ;; If we just finished reading command, redisplay prompt
  960.     (if viper-incomplete-ex-cmd
  961.     (setq ex-file (viper-ex-read-file-name (format ":%s " prompt)))
  962.       ;; file was typed in-line
  963.       (setq ex-file (or ex-file "")))
  964.     ))
  965.  
  966.  
  967. ;; Completes file name or exits minibuffer. If Ex command accepts multiple
  968. ;; file names, arranges to re-enter the minibuffer.
  969. (defun viper-complete-filename-or-exit ()
  970.   (interactive)
  971.   (setq viper-keep-reading-filename t) 
  972.   ;; don't exit if directory---ex-commands don't 
  973.   (cond ((ex-cmd-accepts-multiple-files-p ex-token) (exit-minibuffer))
  974.     ;; apparently the argument to an Ex command is
  975.     ;; supposed to be a shell command
  976.     ((viper-looking-back "^[ \t]*!.*")
  977.      (setq ex-cmdfile t)
  978.      (insert " "))
  979.     (t
  980.      (setq ex-cmdfile nil)
  981.      (minibuffer-complete-word))))
  982.  
  983. (defun viper-handle-! ()
  984.   (interactive)
  985.   (if (and (string=
  986.         (buffer-string) (viper-abbreviate-file-name default-directory))
  987.        (member ex-token '("read" "write")))
  988.       (erase-buffer))
  989.   (insert "!"))
  990.  
  991. (defun ex-cmd-accepts-multiple-files-p (token)
  992.   (member token '("edit" "next" "Next")))
  993.  
  994. ;; Read file name from the minibuffer in an ex command.
  995. ;; If user doesn't enter anything, then "" is returned, i.e., the
  996. ;; prompt-directory is not returned.
  997. (defun viper-ex-read-file-name (prompt)
  998.   (let* ((str "")
  999.      (minibuffer-local-completion-map
  1000.       (copy-keymap minibuffer-local-completion-map))
  1001.      beg end cont val)
  1002.     
  1003.     (viper-add-keymap ex-read-filename-map
  1004.             (if viper-emacs-p 
  1005.             minibuffer-local-completion-map
  1006.               read-file-name-map)) 
  1007.             
  1008.     (setq cont (setq viper-keep-reading-filename t))
  1009.     (while cont
  1010.       (setq viper-keep-reading-filename nil
  1011.         val (read-file-name (concat prompt str) nil default-directory))
  1012.       (if (string-match " " val)
  1013.       (setq val (concat "\\\"" val "\\\"")))
  1014.       (setq str  (concat str (if (equal val "") "" " ")
  1015.              val (if (equal val "") "" " ")))
  1016.              
  1017.       ;; Only edit, next, and Next commands accept multiple files.
  1018.       ;; viper-keep-reading-filename is set in the anonymous function that is
  1019.       ;; bound to " " in ex-read-filename-map.
  1020.       (setq cont (and viper-keep-reading-filename
  1021.               (ex-cmd-accepts-multiple-files-p ex-token)))
  1022.       )
  1023.     
  1024.     (setq beg (string-match "[^ \t]" str)   ; delete leading blanks
  1025.       end (string-match "[ \t]*$" str)) ; delete trailing blanks
  1026.     (if (member ex-token '("read" "write"))
  1027.       (if (string-match "[\t ]*!" str)
  1028.           ;; this is actually a shell command
  1029.           (progn
  1030.         (setq ex-cmdfile t)
  1031.         (setq beg (1+ beg))
  1032.         (setq viper-last-ex-prompt
  1033.               (concat viper-last-ex-prompt " !")))))
  1034.     (substring str (or beg 0) end)))
  1035.  
  1036. ;; Execute ex command using the value of addresses
  1037. (defun viper-execute-ex-command ()
  1038.   (viper-deactivate-mark)
  1039.   (cond ((string= ex-token "args") (ex-args))
  1040.     ((string= ex-token "copy") (ex-copy nil))
  1041.     ((string= ex-token "cd") (ex-cd))
  1042.     ((string= ex-token "chdir") (ex-cd))
  1043.     ((string= ex-token "delete") (ex-delete))
  1044.     ((string= ex-token "edit") (ex-edit))
  1045.     ((string= ex-token "file") (viper-info-on-file))
  1046.     ((string= ex-token "goto") (ex-goto))
  1047.     ((string= ex-token "help") (ex-help))
  1048.     ((string= ex-token "join") (ex-line "join"))
  1049.     ((string= ex-token "kmark") (ex-mark))
  1050.     ((string= ex-token "mark") (ex-mark))
  1051.     ((string= ex-token "map") (ex-map))
  1052.     ((string= ex-token "move") (ex-copy t))
  1053.     ((string= ex-token "next") (ex-next ex-cycle-other-window))
  1054.     ((string= ex-token "Next") (ex-next (not ex-cycle-other-window)))
  1055.     ((string= ex-token "RelatedFile") (ex-next-related-buffer 1))
  1056.     ((string= ex-token "put") (ex-put))
  1057.     ((string= ex-token "pwd") (ex-pwd))
  1058.     ((string= ex-token "preserve") (ex-preserve))
  1059.     ((string= ex-token "PreviousRelatedFile") (ex-next-related-buffer -1))
  1060.     ((string= ex-token "quit") (ex-quit))
  1061.     ((string= ex-token "read") (ex-read))
  1062.     ((string= ex-token "recover") (ex-recover))
  1063.     ((string= ex-token "rewind") (ex-rewind))
  1064.     ((string= ex-token "submitReport") (viper-submit-report))
  1065.     ((string= ex-token "set") (ex-set))
  1066.     ((string= ex-token "shell") (ex-shell))
  1067.     ((string= ex-token "source") (ex-source))
  1068.     ((string= ex-token "sr") (ex-substitute t t))
  1069.     ((string= ex-token "substitute") (ex-substitute))
  1070.     ((string= ex-token "suspend") (suspend-emacs))
  1071.     ((string= ex-token "stop") (suspend-emacs))
  1072.     ((string= ex-token "transfer") (ex-copy nil))
  1073.     ((string= ex-token "buffer") (if ex-cycle-other-window
  1074.                      (viper-switch-to-buffer-other-window)
  1075.                        (viper-switch-to-buffer)))
  1076.     ((string= ex-token "Buffer") (if ex-cycle-other-window
  1077.                      (viper-switch-to-buffer)
  1078.                        (viper-switch-to-buffer-other-window)))
  1079.     ((string= ex-token "tag") (ex-tag))
  1080.     ((string= ex-token "undo") (viper-undo))
  1081.     ((string= ex-token "unmap") (ex-unmap))
  1082.     ((string= ex-token "version") (viper-version))
  1083.     ((string= ex-token "visual") (ex-edit))
  1084.     ((string= ex-token "write") (ex-write nil))
  1085.     ((string= ex-token "Write") (save-some-buffers))
  1086.     ((string= ex-token "wq") (ex-write t))
  1087.     ((string= ex-token "WWrite") (save-some-buffers t)) ; don't ask
  1088.     ((string= ex-token "xit") (ex-write t))
  1089.     ((string= ex-token "yank") (ex-yank))
  1090.     ((string= ex-token "!") (ex-command))
  1091.     ((string= ex-token "=") (ex-line-no))
  1092.     ((string= ex-token ">") (ex-line "right"))
  1093.     ((string= ex-token "<") (ex-line "left"))
  1094.     ((string= ex-token "&") (ex-substitute t))
  1095.     ((string= ex-token "~") (ex-substitute t t))
  1096.     ((or (string= ex-token "append")
  1097.          (string= ex-token "change")
  1098.          (string= ex-token "insert")
  1099.          (string= ex-token "open"))
  1100.      (error "`%s': Obsolete command, not supported by Viper" ex-token))
  1101.     ((or (string= ex-token "abbreviate")
  1102.          (string= ex-token "unabbreviate"))
  1103.      (error
  1104.       "`%s': Vi abbrevs are obsolete. Use the more powerful Emacs abbrevs"
  1105.       ex-token))
  1106.     ((or (string= ex-token "list")
  1107.          (string= ex-token "print")
  1108.          (string= ex-token "z")
  1109.          (string= ex-token "#"))
  1110.      (error "`%s': Command not implemented in Viper" ex-token))
  1111.     (t (error "`%s': %s" ex-token viper-BadExCommand))))
  1112.  
  1113. (defun viper-undisplayed-files ()
  1114.   (mapcar
  1115.    (function 
  1116.     (lambda (b) 
  1117.       (if (null (get-buffer-window b))
  1118.       (let ((f (buffer-file-name b)))
  1119.         (if f f
  1120.           (if ex-cycle-through-non-files 
  1121.           (let ((s (buffer-name b)))
  1122.             (if (string= " " (substring s 0 1))
  1123.             nil
  1124.               s))
  1125.         nil)))
  1126.     nil)))
  1127.    (buffer-list)))
  1128.  
  1129.  
  1130. (defun ex-args ()
  1131.   (let ((l (viper-undisplayed-files))
  1132.     (args "")
  1133.     (file-count 1))
  1134.     (while (not (null l))
  1135.       (if (car l) 
  1136.       (setq args (format "%s %d) %s\n" args file-count (car l))
  1137.         file-count (1+ file-count)))
  1138.       (setq l (cdr l)))
  1139.     (if (string= args "")
  1140.     (message "All files are already displayed")
  1141.       (save-excursion
  1142.     (save-window-excursion
  1143.       (with-output-to-temp-buffer " *viper-info*"
  1144.         (princ "\n\nThese files are not displayed in any window.\n")
  1145.         (princ "\n=============\n")
  1146.         (princ args)
  1147.         (princ "\n=============\n")
  1148.         (princ "\nThe numbers can be given as counts to :next. ")
  1149.         (princ "\n\nPress any key to continue...\n\n"))
  1150.       (viper-read-event))))))
  1151.  
  1152. ;; Ex cd command. Default directory of this buffer changes
  1153. (defun ex-cd ()
  1154.   (viper-get-ex-file)
  1155.   (if (string= ex-file "")
  1156.       (setq ex-file "~"))
  1157.   (setq default-directory (file-name-as-directory (expand-file-name ex-file))))
  1158.  
  1159. ;; Ex copy and move command.  DEL-FLAG means delete
  1160. (defun ex-copy (del-flag)
  1161.   (viper-default-ex-addresses)
  1162.   (let ((address (viper-get-ex-address))
  1163.     (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
  1164.     (goto-char end)
  1165.     (save-excursion
  1166.       (push-mark beg t)
  1167.       (viper-enlarge-region (mark t) (point))
  1168.       (if del-flag
  1169.       (kill-region (point) (mark t))
  1170.     (copy-region-as-kill (point) (mark t)))
  1171.       (if ex-flag
  1172.       (progn
  1173.         (with-output-to-temp-buffer " *copy text*"
  1174.           (princ
  1175.            (if (or del-flag ex-g-flag ex-g-variant)
  1176.            (current-kill 0)
  1177.          (buffer-substring (point) (mark t)))))
  1178.         (condition-case nil
  1179.         (progn
  1180.           (read-string "[Hit return to confirm] ")
  1181.           (save-excursion (kill-buffer " *copy text*")))
  1182.           (quit (save-excursion (kill-buffer " *copy text*"))
  1183.             (signal 'quit nil))))))
  1184.     (if (= address 0)
  1185.     (goto-char (point-min))
  1186.       (goto-char address)
  1187.       (forward-line 1))
  1188.       (insert (current-kill 0))))
  1189.  
  1190. ;; Ex delete command
  1191. (defun ex-delete ()
  1192.   (viper-default-ex-addresses)
  1193.   (viper-get-ex-buffer)
  1194.   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
  1195.     (if (> beg end) (error viper-FirstAddrExceedsSecond))
  1196.     (save-excursion
  1197.       (viper-enlarge-region beg end)
  1198.       (exchange-point-and-mark)
  1199.       (if ex-count
  1200.       (progn
  1201.         (set-mark (point))
  1202.         (forward-line (1- ex-count)))
  1203.     (set-mark end))
  1204.       (viper-enlarge-region (point) (mark t))
  1205.       (if ex-flag
  1206.       ;; show text to be deleted and ask for confirmation
  1207.       (progn
  1208.         (with-output-to-temp-buffer " *delete text*"
  1209.           (princ (buffer-substring (point) (mark t))))
  1210.         (condition-case nil
  1211.         (read-string "[Hit return to confirm] ")
  1212.           (quit
  1213.            (save-excursion (kill-buffer " *delete text*"))
  1214.            (error "")))
  1215.         (save-excursion (kill-buffer " *delete text*")))
  1216.     (if ex-buffer
  1217.         (cond ((viper-valid-register ex-buffer '(Letter))
  1218.            (viper-append-to-register
  1219.             (downcase ex-buffer) (point) (mark t)))
  1220.           ((viper-valid-register ex-buffer)
  1221.            (copy-to-register ex-buffer (point) (mark t) nil))
  1222.           (t (error viper-InvalidRegister ex-buffer))))
  1223.     (kill-region (point) (mark t))))))
  1224.  
  1225.  
  1226.  
  1227. ;; Ex edit command
  1228. ;; In Viper, `e' and `e!' behave identically. In both cases, the user is
  1229. ;; asked if current buffer should really be discarded.
  1230. ;; This command can take multiple file names. It replaces the current buffer
  1231. ;; with the first file in its argument list
  1232. (defun ex-edit (&optional file)
  1233.   (if (not file)
  1234.       (viper-get-ex-file))
  1235.   (cond ((and (string= ex-file "") buffer-file-name)
  1236.      (setq ex-file  (viper-abbreviate-file-name (buffer-file-name))))
  1237.     ((string= ex-file "")
  1238.      (error viper-NoFileSpecified)))
  1239.       
  1240.   (let (msg do-edit)
  1241.     (if buffer-file-name
  1242.     (cond ((buffer-modified-p)
  1243.            (setq msg
  1244.              (format "Buffer %s is modified. Discard changes? "
  1245.                  (buffer-name))
  1246.              do-edit t))
  1247.           ((not (verify-visited-file-modtime (current-buffer)))
  1248.            (setq msg
  1249.              (format "File %s changed on disk.  Reread from disk? "
  1250.                  buffer-file-name)
  1251.              do-edit t))
  1252.           (t (setq do-edit nil))))
  1253.       
  1254.     (if do-edit
  1255.     (if (yes-or-no-p msg)
  1256.         (progn
  1257.           (set-buffer-modified-p nil)
  1258.           (kill-buffer (current-buffer)))
  1259.       (message "Buffer %s was left intact" (buffer-name))))
  1260.     ) ; let
  1261.   
  1262.   (if (null (setq file (get-file-buffer ex-file)))
  1263.       (progn 
  1264.     (ex-find-file ex-file)
  1265.     (or (eq major-mode 'dired-mode)
  1266.         (viper-change-state-to-vi))
  1267.     (goto-char (point-min)))
  1268.     (switch-to-buffer file))
  1269.   (if ex-offset
  1270.       (progn
  1271.     (save-window-excursion
  1272.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1273.       (set-buffer viper-ex-work-buf)
  1274.       (delete-region (point-min) (point-max))
  1275.       (insert ex-offset "\n")
  1276.       (goto-char (point-min)))
  1277.     (goto-char (viper-get-ex-address))
  1278.     (beginning-of-line)))
  1279.   (ex-fixup-history viper-last-ex-prompt ex-file))
  1280.  
  1281. ;; Find-file FILESPEC if it appears to specify a single file.
  1282. ;; Otherwise, assume that FILES{EC is a wildcard.
  1283. ;; In this case, split it into substrings separated by newlines.
  1284. ;; Each line is assumed to be a file name. find-file's each file thus obtained.
  1285. (defun ex-find-file (filespec)
  1286.   (let ((nonstandard-filename-chars "[^-a-zA-Z0-9_./,~$\\]"))
  1287.     (cond ((file-exists-p filespec) (find-file filespec))
  1288.       ((string-match nonstandard-filename-chars  filespec)
  1289.        (funcall ex-nontrivial-find-file-function filespec))
  1290.       (t (find-file filespec)))
  1291.     ))
  1292.  
  1293.  
  1294. ;; Ex global command
  1295. ;; This is executed in response to:
  1296. ;;        :global "pattern" ex-command
  1297. ;;        :vglobal "pattern" ex-command
  1298. ;; :global executes ex-command on all lines matching <pattern>
  1299. ;; :vglobal executes ex-command on all lines that don't match <pattern>
  1300. ;;
  1301. ;; With VARIANT nil, this functions executes :global
  1302. ;; With VARIANT t, executes :vglobal
  1303. (defun ex-global (variant)
  1304.   (let ((gcommand ex-token))
  1305.     (if (or ex-g-flag ex-g-variant)
  1306.     (error "`%s' within `global' is not allowed" gcommand)
  1307.       (if variant
  1308.       (setq ex-g-flag nil
  1309.         ex-g-variant t)
  1310.     (setq ex-g-flag t
  1311.           ex-g-variant nil)))
  1312.     (viper-get-ex-pat)
  1313.     (if (null ex-token)
  1314.     (error "`%s': Missing regular expression" gcommand)))
  1315.   
  1316.   (if (string= ex-token "")
  1317.       (if (null viper-s-string)
  1318.       (error viper-NoPrevSearch)
  1319.     (setq ex-g-pat viper-s-string))
  1320.     (setq ex-g-pat ex-token
  1321.       viper-s-string ex-token))
  1322.   (if (null ex-addresses)
  1323.       (setq ex-addresses (list (point-max) (point-min)))
  1324.     (viper-default-ex-addresses))
  1325.   (let ((marks nil)
  1326.     (mark-count 0)
  1327.     (end (car ex-addresses))
  1328.     (beg (car (cdr ex-addresses)))
  1329.     com-str)
  1330.     (if (> beg end) (error viper-FirstAddrExceedsSecond))
  1331.     (save-excursion
  1332.       (viper-enlarge-region beg end)
  1333.       (exchange-point-and-mark)
  1334.       (let ((cont t) (limit (point-marker)))
  1335.     (exchange-point-and-mark)
  1336.     ;; skip the last line if empty
  1337.     (beginning-of-line)
  1338.     (if (eobp) (viper-backward-char-carefully))
  1339.     (while (and cont (not (bobp)) (>= (point) limit))
  1340.       (beginning-of-line)
  1341.       (set-mark (point))
  1342.       (end-of-line)
  1343.       (let ((found (re-search-backward ex-g-pat (mark t) t)))
  1344.         (if (or (and ex-g-flag found)
  1345.             (and ex-g-variant (not found)))
  1346.         (progn
  1347.           (end-of-line)
  1348.           (setq mark-count (1+ mark-count))
  1349.           (setq marks (cons (point-marker) marks)))))
  1350.       (beginning-of-line)
  1351.       (if (bobp) (setq cont nil)
  1352.         (forward-line -1)
  1353.         (end-of-line)))))
  1354.     (save-window-excursion
  1355.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1356.       (set-buffer viper-ex-work-buf)
  1357.       (setq com-str (buffer-substring (1+ (point)) (1- (point-max)))))
  1358.     (while marks
  1359.       (goto-char (car marks))
  1360.       (viper-ex com-str)
  1361.       (setq mark-count (1- mark-count))
  1362.       (setq marks (cdr marks)))))
  1363.  
  1364. ;; Ex goto command
  1365. (defun ex-goto ()
  1366.   (if (null ex-addresses)
  1367.       (setq ex-addresses (cons (point) nil)))
  1368.   (push-mark (point) t)
  1369.   (goto-char (car ex-addresses))
  1370.   (beginning-of-line))
  1371.  
  1372. ;; Ex line commands.  COM is join, shift-right or shift-left
  1373. (defun ex-line (com)
  1374.   (viper-default-ex-addresses)
  1375.   (viper-get-ex-count)
  1376.   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))) point)
  1377.     (if (> beg end) (error viper-FirstAddrExceedsSecond))
  1378.     (save-excursion
  1379.       (viper-enlarge-region beg end)
  1380.       (exchange-point-and-mark)
  1381.       (if ex-count
  1382.       (progn
  1383.         (set-mark (point))
  1384.         (forward-line ex-count)))
  1385.       (if ex-flag
  1386.       ;; show text to be joined and ask for confirmation
  1387.       (progn
  1388.         (with-output-to-temp-buffer " *join text*"
  1389.           (princ (buffer-substring (point) (mark t))))
  1390.         (condition-case nil
  1391.         (progn
  1392.           (read-string "[Hit return to confirm] ")
  1393.           (ex-line-subr com (point) (mark t)))
  1394.           (quit (ding)))
  1395.         (save-excursion (kill-buffer " *join text*")))
  1396.     (ex-line-subr com (point) (mark t)))
  1397.       (setq point (point)))
  1398.     (goto-char (1- point))
  1399.     (beginning-of-line)))
  1400.  
  1401. (defun ex-line-subr (com beg end)
  1402.   (cond ((string= com "join")
  1403.      (goto-char (min beg end))
  1404.      (while (and (not (eobp)) (< (point) (max beg end)))
  1405.        (end-of-line)
  1406.        (if (and (<= (point) (max beg end)) (not (eobp)))
  1407.            (progn
  1408.          (forward-line 1)
  1409.          (delete-region (point) (1- (point)))
  1410.          (if (not ex-variant) (fixup-whitespace))))))
  1411.     ((or (string= com "right") (string= com "left"))
  1412.      (indent-rigidly
  1413.       (min beg end) (max beg end)
  1414.       (if (string= com "right") viper-shift-width (- viper-shift-width)))
  1415.      (goto-char (max beg end))
  1416.      (end-of-line)
  1417.      (viper-forward-char-carefully))))
  1418.  
  1419.  
  1420. ;; Ex mark command
  1421. (defun ex-mark ()
  1422.   (let (char)
  1423.     (if (null ex-addresses)
  1424.     (setq ex-addresses
  1425.           (cons (point) nil)))
  1426.     (save-window-excursion
  1427.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1428.       (set-buffer viper-ex-work-buf)
  1429.       (skip-chars-forward " \t")
  1430.       (if (looking-at "[a-z]")
  1431.       (progn
  1432.         (setq char (following-char))
  1433.         (forward-char 1)
  1434.         (skip-chars-forward " \t")
  1435.         (if (not (looking-at "[\n|]"))
  1436.         (error "`%s': %s" ex-token viper-SpuriousText)))
  1437.     (error "`%s' requires a following letter" ex-token)))
  1438.     (save-excursion
  1439.       (goto-char (car ex-addresses))
  1440.       (point-to-register (1+ (- char ?a))))))
  1441.  
  1442.     
  1443.       
  1444. ;; Alternate file is the file next to the first one in the buffer ring
  1445. (defun ex-next (cycle-other-window &optional find-alt-file)
  1446.   (catch 'ex-edit
  1447.     (let (count l)
  1448.       (if (not find-alt-file) 
  1449.       (progn
  1450.         (viper-get-ex-file)
  1451.         (if (or (char-or-string-p ex-offset)
  1452.             (and (not (string= "" ex-file)) 
  1453.                  (not (string-match "^[0-9]+$" ex-file))))
  1454.         (progn
  1455.           (ex-edit t)
  1456.           (throw 'ex-edit nil))
  1457.           (setq count (string-to-int ex-file))
  1458.           (if (= count 0) (setq count 1))
  1459.           (if (< count 0) (error "Usage: `next <count>' (count >= 0)"))))
  1460.     (setq count 1))
  1461.       (setq l (viper-undisplayed-files))
  1462.       (while (> count 0)
  1463.     (while (and (not (null l)) (null (car l)))
  1464.       (setq l (cdr l)))
  1465.     (setq count (1- count))
  1466.     (if (> count 0)
  1467.         (setq l (cdr l))))
  1468.       (if find-alt-file (car l)
  1469.     (progn
  1470.       (if (and (car l) (get-file-buffer (car l)))
  1471.           (let* ((w (if cycle-other-window
  1472.                 (get-lru-window) (selected-window)))
  1473.              (b (window-buffer w)))
  1474.         (set-window-buffer w (get-file-buffer (car l)))
  1475.         (bury-buffer b)
  1476.         ;; this puts "next <count>" in the ex-command history
  1477.         (ex-fixup-history viper-last-ex-prompt ex-file))
  1478.         (error "Not that many undisplayed files")))))))
  1479.  
  1480.  
  1481. (defun ex-next-related-buffer (direction &optional no-recursion)
  1482.   
  1483.   (viper-ring-rotate1 viper-related-files-and-buffers-ring direction)
  1484.   
  1485.   (let ((file-or-buffer-name 
  1486.      (viper-current-ring-item viper-related-files-and-buffers-ring))
  1487.     (old-ring viper-related-files-and-buffers-ring)
  1488.     (old-win (selected-window))
  1489.     skip-rest buf wind)
  1490.     
  1491.     (or (and (ring-p viper-related-files-and-buffers-ring)
  1492.          (> (ring-length viper-related-files-and-buffers-ring) 0))
  1493.     (error "This buffer has no related files or buffers"))
  1494.     
  1495.     (or (stringp file-or-buffer-name)
  1496.     (error
  1497.      "File and buffer names must be strings, %S" file-or-buffer-name))
  1498.     
  1499.     (setq buf (cond ((get-buffer file-or-buffer-name))
  1500.             ((file-exists-p file-or-buffer-name)
  1501.              (find-file-noselect file-or-buffer-name))
  1502.             ))
  1503.     
  1504.     (if (not (viper-buffer-live-p buf))
  1505.     (error "Didn't find buffer %S or file %S"
  1506.            file-or-buffer-name
  1507.            (viper-abbreviate-file-name
  1508.         (expand-file-name file-or-buffer-name))))
  1509.       
  1510.     (if (equal buf (current-buffer))
  1511.     (or no-recursion
  1512.         ;; try again
  1513.         (progn
  1514.           (setq skip-rest t)
  1515.           (ex-next-related-buffer direction 'norecursion))))
  1516.     
  1517.     (if skip-rest
  1518.     ()
  1519.       ;; setup buffer
  1520.       (if (setq wind (viper-get-visible-buffer-window buf))
  1521.       ()
  1522.     (setq wind (get-lru-window (if viper-xemacs-p nil 'visible)))
  1523.     (set-window-buffer wind buf))
  1524.         
  1525.       (if (viper-window-display-p)
  1526.       (progn
  1527.         (raise-frame (window-frame wind))
  1528.         (if (equal (window-frame wind) (window-frame old-win))
  1529.         (save-window-excursion (select-window wind) (sit-for 1))
  1530.           (select-window wind)))
  1531.     (save-window-excursion (select-window wind) (sit-for 1)))
  1532.     
  1533.       (save-excursion
  1534.     (set-buffer buf)
  1535.     (setq viper-related-files-and-buffers-ring old-ring))
  1536.       
  1537.       (setq viper-local-search-start-marker (point-marker))
  1538.       )))
  1539.   
  1540.     
  1541. ;; Force auto save
  1542. (defun ex-preserve ()
  1543.   (message "Autosaving all buffers that need to be saved...")
  1544.   (do-auto-save t))
  1545.  
  1546. ;; Ex put
  1547. (defun ex-put ()
  1548.   (let ((point (if (null ex-addresses) (point) (car ex-addresses))))
  1549.     (viper-get-ex-buffer)
  1550.     (setq viper-use-register ex-buffer)
  1551.     (goto-char point)
  1552.     (if (bobp) (viper-Put-back 1) (viper-put-back 1))))
  1553.  
  1554. ;; Ex print working directory
  1555. (defun ex-pwd ()
  1556.   (message default-directory))
  1557.  
  1558. ;; Ex quit command
  1559. (defun ex-quit ()
  1560.   ;; skip "!", if it is q!. In Viper q!, w!, etc., behave as q, w, etc.
  1561.   (save-excursion
  1562.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1563.     (set-buffer viper-ex-work-buf)
  1564.     (if (looking-at "!") (forward-char 1)))
  1565.   (if (< viper-expert-level 3)
  1566.       (save-buffers-kill-emacs)
  1567.     (kill-buffer (current-buffer))))
  1568.  
  1569.  
  1570. ;; Ex read command
  1571. (defun ex-read ()
  1572.   (viper-get-ex-file)
  1573.   (let ((point (if (null ex-addresses) (point) (car ex-addresses)))
  1574.     command)
  1575.     (goto-char point)
  1576.     (viper-add-newline-at-eob-if-necessary)
  1577.     (if (not (or (bobp) (eobp))) (forward-line 1))
  1578.     (if (and (not ex-variant) (string= ex-file ""))
  1579.     (progn
  1580.       (if (null buffer-file-name)
  1581.           (error viper-NoFileSpecified))
  1582.       (setq ex-file buffer-file-name)))
  1583.     (if ex-cmdfile
  1584.     (progn
  1585.       (setq command 
  1586.         (concat (ex-expand-filsyms ex-file (current-buffer))
  1587.             ex-cmdfile-args))
  1588.       (shell-command command t))
  1589.       (insert-file-contents ex-file)))
  1590.   (ex-fixup-history viper-last-ex-prompt ex-file ex-cmdfile-args))
  1591.   
  1592. ;; this function fixes ex-history for some commands like ex-read, ex-edit
  1593. (defun ex-fixup-history (&rest args)  
  1594.   (setq viper-ex-history
  1595.     (cons (mapconcat 'identity args " ") (cdr viper-ex-history))))
  1596.   
  1597.  
  1598. ;; Ex recover from emacs \#file\#
  1599. (defun ex-recover ()
  1600.   (viper-get-ex-file)
  1601.   (if (or ex-append ex-offset)
  1602.       (error "`recover': %s" viper-SpuriousText))
  1603.   (if (string= ex-file "")
  1604.       (progn
  1605.     (if (null buffer-file-name)
  1606.         (error "This buffer isn't visiting any file"))
  1607.     (setq ex-file buffer-file-name))
  1608.     (setq ex-file (expand-file-name ex-file)))
  1609.   (if (and (not (string= ex-file (buffer-file-name)))
  1610.        (buffer-modified-p)
  1611.        (not ex-variant))
  1612.       (error "No write since last change \(:rec! overrides\)"))
  1613.   (recover-file ex-file))
  1614.  
  1615. ;; Tell that `rewind' is obsolete and to use `:next count' instead
  1616. (defun ex-rewind ()
  1617.   (message
  1618.    "Use `:n <count>' instead. Counts are obtained from the `:args' command"))
  1619.  
  1620.  
  1621. ;; read variable name for ex-set
  1622. (defun ex-set-read-variable ()
  1623.   (let ((minibuffer-local-completion-map
  1624.      (copy-keymap minibuffer-local-completion-map))
  1625.     (cursor-in-echo-area t)
  1626.     str batch)
  1627.     (define-key
  1628.       minibuffer-local-completion-map " " 'minibuffer-complete-and-exit)
  1629.     (define-key minibuffer-local-completion-map "=" 'exit-minibuffer)
  1630.     (if (viper-set-unread-command-events
  1631.      (ex-get-inline-cmd-args "[ \t]*[a-zA-Z]*[ \t]*" nil "\C-m"))
  1632.     (progn
  1633.       (setq batch t)
  1634.       (viper-set-unread-command-events ?\C-m)))
  1635.     (message ":set  <Variable> [= <Value>]")
  1636.     (or batch (sit-for 2))
  1637.     
  1638.     (while (string-match "^[ \\t\\n]*$"
  1639.              (setq str
  1640.                    (completing-read ":set " ex-variable-alist)))
  1641.       (message ":set <Variable> [= <Value>]")
  1642.       ;; if there are unread events, don't wait
  1643.       (or (viper-set-unread-command-events "") (sit-for 2))
  1644.       ) ; while
  1645.     str))
  1646.  
  1647.  
  1648. (defun ex-set ()
  1649.   (let ((var (ex-set-read-variable))
  1650.     (val 0)
  1651.     (set-cmd "setq")
  1652.     (ask-if-save t)
  1653.     (auto-cmd-label "; don't touch or else...")
  1654.     (delete-turn-on-auto-fill-pattern
  1655.      "([ \t]*add-hook[ \t]+'viper-insert-state-hooks[ \t]+'turn-on-auto-fill.*)")
  1656.     actual-lisp-cmd lisp-cmd-del-pattern
  1657.     val2 orig-var)
  1658.     (setq orig-var var)
  1659.     (cond ((string= var "all")
  1660.        (setq ask-if-save nil
  1661.          set-cmd nil))
  1662.       ((member var '("ai" "autoindent"))
  1663.        (setq var "viper-auto-indent"
  1664.          set-cmd "setq"
  1665.          ask-if-save nil
  1666.          val "t"))
  1667.       ((member var '("ai-g" "autoindent-global"))
  1668.        (kill-local-variable 'viper-auto-indent)
  1669.        (setq var "viper-auto-indent"
  1670.          set-cmd "setq-default"
  1671.          val "t"))
  1672.       ((member var '("noai" "noautoindent"))
  1673.        (setq var "viper-auto-indent"
  1674.          ask-if-save nil
  1675.          val "nil"))
  1676.       ((member var '("noai-g" "noautoindent-global"))
  1677.        (kill-local-variable 'viper-auto-indent)
  1678.        (setq var "viper-auto-indent"
  1679.          set-cmd "setq-default"
  1680.          val "nil"))
  1681.       ((member var '("ic" "ignorecase"))
  1682.        (setq var "viper-case-fold-search"
  1683.          val "t"))
  1684.       ((member var '("noic" "noignorecase"))
  1685.        (setq var "viper-case-fold-search"
  1686.          val "nil"))
  1687.       ((member var '("ma" "magic"))
  1688.        (setq var "viper-re-search"
  1689.          val "t"))
  1690.         ((member var '("noma" "nomagic"))
  1691.        (setq var "viper-re-search"
  1692.          val "nil"))
  1693.       ((member var '("ro" "readonly"))
  1694.        (setq var "buffer-read-only"
  1695.          val "t"))
  1696.       ((member var '("noro" "noreadonly"))
  1697.        (setq var "buffer-read-only"
  1698.          val "nil"))
  1699.       ((member var '("sm" "showmatch"))
  1700.        (setq var "blink-matching-paren"
  1701.          val "t"))
  1702.       ((member var '("nosm" "noshowmatch"))
  1703.        (setq var "blink-matching-paren"
  1704.          val "nil"))
  1705.       ((member var '("ws" "wrapscan"))
  1706.        (setq var "viper-search-wrap-around-t"
  1707.          val "t"))
  1708.       ((member var '("nows" "nowrapscan"))
  1709.        (setq var "viper-search-wrap-around-t"
  1710.          val "nil")))
  1711.     (if (and set-cmd (eq val 0)) ; value must be set by the user
  1712.     (let ((cursor-in-echo-area t))
  1713.       (message ":set %s = <Value>" var)
  1714.       ;; if there are unread events, don't wait
  1715.       (or (viper-set-unread-command-events "") (sit-for 2))
  1716.       (setq val (read-string (format ":set %s = " var)))
  1717.       (ex-fixup-history "set" orig-var val)
  1718.       
  1719.       ;; check numerical values
  1720.       (if (member var
  1721.               '("sw" "shiftwidth"
  1722.             "ts" "tabstop"
  1723.             "ts-g" "tabstop-global"
  1724.             "wm" "wrapmargin")) 
  1725.           (condition-case nil
  1726.           (or (numberp (setq val2 (car (read-from-string val))))
  1727.               (error "%s: Invalid value, numberp, %S" var val))
  1728.         (error
  1729.          (error "%s: Invalid value, numberp, %S" var val))))
  1730.           
  1731.       (cond
  1732.        ((member var '("sw" "shiftwidth"))
  1733.         (setq var "viper-shift-width"))
  1734.        ((member var '("ts" "tabstop"))
  1735.         ;; make it take effect in curr buff and new bufs
  1736.         (setq var "tab-width"
  1737.           set-cmd "setq"
  1738.           ask-if-save nil))
  1739.        ((member var '("ts-g" "tabstop-global"))
  1740.         (kill-local-variable 'tab-width)
  1741.         (setq var "tab-width"
  1742.           set-cmd "setq-default"))
  1743.        ((member var '("wm" "wrapmargin"))
  1744.         ;; make it take effect in curr buff and new bufs
  1745.         (kill-local-variable 'fill-column) 
  1746.         (setq var "fill-column" 
  1747.           val (format "(- (window-width) %s)" val)
  1748.           set-cmd "setq-default"))
  1749.        ((member var '("sh" "shell"))
  1750.         (setq var "explicit-shell-file-name"
  1751.           val (format "\"%s\"" val)))))
  1752.       (ex-fixup-history "set" orig-var))
  1753.     
  1754.     (if set-cmd
  1755.     (setq actual-lisp-cmd
  1756.           (format "\n(%s %s %s) %s" set-cmd var val auto-cmd-label)
  1757.           lisp-cmd-del-pattern
  1758.           (format "^\n?[ \t]*([ \t]*%s[ \t]+%s[ \t].*)[ \t]*%s"
  1759.               set-cmd var auto-cmd-label)))
  1760.     
  1761.     (if (and ask-if-save
  1762.          (y-or-n-p (format "Do you want to save this setting in %s "
  1763.                    viper-custom-file-name)))
  1764.     (progn
  1765.       (viper-save-string-in-file 
  1766.        actual-lisp-cmd viper-custom-file-name
  1767.        ;; del pattern
  1768.        lisp-cmd-del-pattern)
  1769.       (if (string= var "fill-column")
  1770.           (if (> val2 0)
  1771.           (viper-save-string-in-file
  1772.            (concat
  1773.             "(add-hook 'viper-insert-state-hooks 'turn-on-auto-fill) "
  1774.             auto-cmd-label)
  1775.            viper-custom-file-name
  1776.            delete-turn-on-auto-fill-pattern)
  1777.         (viper-save-string-in-file
  1778.          nil viper-custom-file-name delete-turn-on-auto-fill-pattern)
  1779.         (viper-save-string-in-file
  1780.          nil viper-custom-file-name
  1781.          ;; del pattern
  1782.          lisp-cmd-del-pattern)
  1783.         ))
  1784.       ))
  1785.     
  1786.     (if set-cmd
  1787.     (message "%s %s %s"
  1788.          set-cmd var
  1789.          (if (string-match "^[ \t]*$" val)
  1790.              (format "%S" val)
  1791.            val)))
  1792.     (if actual-lisp-cmd
  1793.     (eval (car (read-from-string actual-lisp-cmd))))
  1794.     (if (string= var "fill-column")
  1795.     (if (> val2 0)
  1796.         (auto-fill-mode 1)
  1797.       (auto-fill-mode -1)))
  1798.     (if (string= var "all") (ex-show-vars))
  1799.     ))
  1800.  
  1801. ;; In inline args, skip regex-forw and (optionally) chars-back.
  1802. ;; Optional 3d arg is a string that should replace ' ' to prevent its
  1803. ;; special meaning
  1804. (defun ex-get-inline-cmd-args (regex-forw &optional chars-back replace-str)
  1805.   (save-excursion
  1806.     (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1807.     (set-buffer viper-ex-work-buf)
  1808.     (goto-char (point-min))
  1809.     (re-search-forward regex-forw nil t)
  1810.     (let ((beg (point))
  1811.       end)
  1812.       (goto-char (point-max))
  1813.       (if chars-back
  1814.       (skip-chars-backward chars-back)
  1815.     (skip-chars-backward " \t\n\C-m"))
  1816.       (setq end (point))
  1817.       ;; replace SPC with `=' to suppress the special meaning SPC has
  1818.       ;; in Ex commands
  1819.       (goto-char beg)
  1820.       (if replace-str
  1821.       (while (re-search-forward " +" nil t)
  1822.         (replace-match replace-str nil t)
  1823.         (viper-forward-char-carefully)))
  1824.       (goto-char end)
  1825.       (buffer-substring beg end))))
  1826.  
  1827.  
  1828. ;; Ex shell command
  1829. (defun ex-shell ()
  1830.   (shell))
  1831.   
  1832. ;; Viper help. Invokes Info
  1833. (defun ex-help ()
  1834.   (condition-case nil
  1835.       (progn
  1836.     (pop-to-buffer (get-buffer-create "*info*"))
  1837.     (info (if viper-xemacs-p "viper.info" "viper"))
  1838.     (message "Type `i' to search for a specific topic"))
  1839.     (error (beep 1)
  1840.        (with-output-to-temp-buffer " *viper-info*"
  1841.          (princ (format "
  1842. The Info file for Viper does not seem to be installed.
  1843.  
  1844. This file is part of the standard distribution of %sEmacs.
  1845. Please contact your system administrator. "
  1846.                 (if viper-xemacs-p "X" "")
  1847.                 ))))))
  1848.  
  1849. ;; Ex source command. Loads the file specified as argument or `~/.viper'
  1850. (defun ex-source ()
  1851.   (viper-get-ex-file)
  1852.   (if (string= ex-file "")
  1853.       (load viper-custom-file-name)
  1854.     (load ex-file)))
  1855.  
  1856. ;; Ex substitute command
  1857. ;; If REPEAT use previous regexp which is ex-reg-exp or viper-s-string
  1858. (defun ex-substitute (&optional repeat r-flag) 
  1859.   (let ((opt-g nil)
  1860.     (opt-c nil)
  1861.     (matched-pos nil)
  1862.     (case-fold-search viper-case-fold-search)
  1863.     delim pat repl)
  1864.     (if repeat (setq ex-token nil) (setq delim (viper-get-ex-pat)))
  1865.     (if (null ex-token)
  1866.     (progn
  1867.       (setq pat (if r-flag viper-s-string ex-reg-exp))
  1868.       (or (stringp pat)
  1869.           (error "No previous pattern to use in substitution"))
  1870.       (setq repl ex-repl
  1871.         delim (string-to-char pat)))
  1872.       (setq pat (if (string= ex-token "") viper-s-string ex-token))
  1873.       (setq viper-s-string pat
  1874.         ex-reg-exp pat)
  1875.       (setq delim (viper-get-ex-pat))
  1876.       (if (null ex-token)
  1877.       (setq ex-token ""
  1878.         ex-repl "")
  1879.     (setq repl ex-token
  1880.           ex-repl ex-token)))
  1881.     (while (viper-get-ex-opt-gc delim)
  1882.       (if (string= ex-token "g") (setq opt-g t) (setq opt-c t)))
  1883.     (viper-get-ex-count)
  1884.     (if ex-count
  1885.     (save-excursion
  1886.       (if ex-addresses (goto-char (car ex-addresses)))
  1887.       (set-mark (point))
  1888.       (forward-line (1- ex-count))
  1889.       (setq ex-addresses (cons (point) (cons (mark t) nil))))
  1890.       (if (null ex-addresses)
  1891.       (setq ex-addresses (cons (point) (cons (point) nil)))
  1892.     (if (null (cdr ex-addresses))
  1893.         (setq ex-addresses (cons (car ex-addresses) ex-addresses)))))
  1894.                     ;(setq G opt-g)
  1895.     (let ((beg (car ex-addresses))
  1896.       (end (car (cdr ex-addresses)))
  1897.       eol-mark)
  1898.       (save-excursion
  1899.     (viper-enlarge-region beg end)
  1900.     (let ((limit (save-excursion
  1901.                (goto-char (max (point) (mark t)))
  1902.                (point-marker))))
  1903.       (goto-char (min (point) (mark t)))
  1904.       (while (< (point) limit)
  1905.         (end-of-line)
  1906.         (setq eol-mark (point-marker))
  1907.         (beginning-of-line)
  1908.         (if opt-g
  1909.         (progn
  1910.           (while (and (not (eolp))
  1911.                   (re-search-forward pat eol-mark t))
  1912.             (if (or (not opt-c) (y-or-n-p "Replace? "))
  1913.             (progn
  1914.               (setq matched-pos (point))
  1915.               (if (not (stringp repl))
  1916.                   (error "Can't perform Ex substitution: No previous replacement pattern"))
  1917.               (replace-match repl t))))
  1918.           (end-of-line)
  1919.           (viper-forward-char-carefully))
  1920.           (if (null pat)
  1921.           (error
  1922.            "Can't repeat Ex substitution: No previous regular expression"))
  1923.           (if (and (re-search-forward pat eol-mark t)
  1924.                (or (not opt-c) (y-or-n-p "Replace? ")))
  1925.           (progn
  1926.             (setq matched-pos (point))
  1927.             (if (not (stringp repl))
  1928.             (error "Can't perform Ex substitution: No previous replacement pattern"))
  1929.             (replace-match repl t)))
  1930.           (end-of-line)
  1931.           (viper-forward-char-carefully))))))
  1932.     (if matched-pos (goto-char matched-pos))
  1933.     (beginning-of-line)
  1934.     (if opt-c (message "done"))))
  1935.  
  1936. ;; Ex tag command
  1937. (defun ex-tag ()
  1938.   (let (tag)
  1939.     (save-window-excursion
  1940.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  1941.       (set-buffer viper-ex-work-buf)
  1942.       (skip-chars-forward " \t")
  1943.       (set-mark (point))
  1944.       (skip-chars-forward "^ |\t\n")
  1945.       (setq tag (buffer-substring (mark t) (point))))
  1946.     (if (not (string= tag "")) (setq ex-tag tag))
  1947.     (viper-change-state-to-emacs)
  1948.     (condition-case conds
  1949.     (progn
  1950.       (if (string= tag "")
  1951.           (find-tag ex-tag t)
  1952.         (find-tag-other-window ex-tag))
  1953.       (viper-change-state-to-vi))
  1954.       (error
  1955.        (viper-change-state-to-vi)
  1956.        (viper-message-conditions conds)))))
  1957.  
  1958. ;; Ex write command
  1959. (defun ex-write (q-flag)
  1960.   (viper-default-ex-addresses t)
  1961.   (viper-get-ex-file)
  1962.   (let ((end (car ex-addresses))
  1963.     (beg (car (cdr ex-addresses))) 
  1964.     (orig-buf (current-buffer))
  1965.     (orig-buf-file-name (buffer-file-name))
  1966.     (orig-buf-name (buffer-name))
  1967.     (buff-changed-p (buffer-modified-p))
  1968.     temp-buf writing-same-file region
  1969.     file-exists writing-whole-file)
  1970.     (if (> beg end) (error viper-FirstAddrExceedsSecond))
  1971.     (if ex-cmdfile
  1972.     (progn
  1973.       (viper-enlarge-region beg end)
  1974.       (shell-command-on-region (point) (mark t) 
  1975.                    (concat ex-file ex-cmdfile-args)))
  1976.       (if (and (string= ex-file "") (not (buffer-file-name)))
  1977.       (setq ex-file
  1978.         (read-file-name
  1979.          (format "Buffer %s isn't visiting any file. File to save in: "
  1980.              (buffer-name)))))
  1981.       
  1982.       (setq writing-whole-file (and (= (point-min) beg) (= (point-max) end))
  1983.         ex-file (if (string= ex-file "")
  1984.             (buffer-file-name)
  1985.               (expand-file-name ex-file)))
  1986.       ;; if ex-file is a directory use the file portion of the buffer file name
  1987.       (if (and (file-directory-p ex-file)
  1988.            buffer-file-name
  1989.            (not (file-directory-p buffer-file-name)))
  1990.       (setq ex-file
  1991.         (concat (file-name-as-directory ex-file)
  1992.             (file-name-nondirectory buffer-file-name))))
  1993.       
  1994.       (setq file-exists (file-exists-p ex-file)
  1995.         writing-same-file (string= ex-file (buffer-file-name)))
  1996.  
  1997.       (if (and writing-whole-file writing-same-file)
  1998.       (if (not (buffer-modified-p))
  1999.           (message "(No changes need to be saved)")
  2000.         (save-buffer)
  2001.         (save-restriction
  2002.          (widen)
  2003.          (ex-write-info file-exists ex-file (point-min) (point-max))
  2004.          ))
  2005.     ;; writing some other file or portion of the current file
  2006.     (cond ((and file-exists
  2007.             (not writing-same-file)
  2008.             (not (yes-or-no-p
  2009.               (format "File %s exists. Overwrite? " ex-file))))
  2010.            (error "Quit"))
  2011.           ((and writing-whole-file (not ex-append))
  2012.            (unwind-protect
  2013.            (progn
  2014.              (set-visited-file-name ex-file)
  2015.              (set-buffer-modified-p t)
  2016.              (save-buffer))
  2017.          ;; restore the buffer file name
  2018.          (set-visited-file-name orig-buf-file-name)
  2019.          (set-buffer-modified-p buff-changed-p)
  2020.          ;; If the buffer wasn't visiting a file, restore buffer name.
  2021.          ;; Name could've been changed by packages such as uniquify.
  2022.          (or orig-buf-file-name
  2023.              (progn
  2024.                (unlock-buffer)
  2025.                (rename-buffer orig-buf-name))))
  2026.            (save-restriction
  2027.          (widen)
  2028.          (ex-write-info
  2029.           file-exists ex-file (point-min) (point-max))))
  2030.           (t ; writing a region
  2031.            (unwind-protect 
  2032.            (save-excursion
  2033.              (viper-enlarge-region beg end)
  2034.              (setq region (buffer-substring (point) (mark t)))
  2035.              ;; create temp buffer for the region
  2036.              (setq temp-buf (get-buffer-create " *ex-write*"))
  2037.              (set-buffer temp-buf)
  2038.              (set-visited-file-name ex-file 'noquerry)
  2039.              (erase-buffer)
  2040.              (if (and file-exists ex-append)
  2041.              (insert-file-contents ex-file))
  2042.              (goto-char (point-max))
  2043.              (insert region)
  2044.              (save-buffer)
  2045.              (ex-write-info
  2046.               file-exists ex-file (point-min) (point-max))
  2047.              ))
  2048.            (set-buffer temp-buf)
  2049.            (set-buffer-modified-p nil)
  2050.            (kill-buffer temp-buf))
  2051.           ))
  2052.       (set-buffer orig-buf)
  2053.       ;; this prevents the loss of data if writing part of the buffer
  2054.       (if (and (buffer-file-name) writing-same-file)
  2055.       (set-visited-file-modtime))
  2056.       (or writing-whole-file 
  2057.       (not writing-same-file)
  2058.       (set-buffer-modified-p t))
  2059.       (if q-flag
  2060.       (if (< viper-expert-level 2)
  2061.           (save-buffers-kill-emacs)
  2062.         (kill-buffer (current-buffer))))
  2063.       )))
  2064.       
  2065.  
  2066. (defun ex-write-info (exists file-name beg end)
  2067.   (message "`%s'%s %d lines, %d characters"
  2068.        (viper-abbreviate-file-name file-name)
  2069.        (if exists "" " [New file]")
  2070.        (count-lines beg (min (1+ end) (point-max)))
  2071.        (- end beg)))
  2072.  
  2073. ;; Ex yank command
  2074. (defun ex-yank ()
  2075.   (viper-default-ex-addresses)
  2076.   (viper-get-ex-buffer)
  2077.   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
  2078.     (if (> beg end) (error viper-FirstAddrExceedsSecond))
  2079.     (save-excursion
  2080.       (viper-enlarge-region beg end)
  2081.       (exchange-point-and-mark)
  2082.       (if (or ex-g-flag ex-g-variant)
  2083.       (error "Can't execute `yank' within `global'"))
  2084.       (if ex-count
  2085.       (progn
  2086.         (set-mark (point))
  2087.         (forward-line (1- ex-count)))
  2088.     (set-mark end))
  2089.       (viper-enlarge-region (point) (mark t))
  2090.       (if ex-flag (error "`yank': %s" viper-SpuriousText))
  2091.       (if ex-buffer
  2092.       (cond ((viper-valid-register ex-buffer '(Letter))
  2093.          (viper-append-to-register
  2094.           (downcase ex-buffer) (point) (mark t)))
  2095.         ((viper-valid-register ex-buffer)
  2096.          (copy-to-register ex-buffer (point) (mark t) nil))
  2097.         (t (error viper-InvalidRegister ex-buffer))))
  2098.       (copy-region-as-kill (point) (mark t)))))
  2099.  
  2100. ;; Execute shell command
  2101. (defun ex-command ()
  2102.   (let (command)
  2103.     (save-window-excursion
  2104.       (setq viper-ex-work-buf (get-buffer-create viper-ex-work-buf-name)) 
  2105.       (set-buffer viper-ex-work-buf)
  2106.       (skip-chars-forward " \t")
  2107.       (setq command (buffer-substring (point) (point-max)))
  2108.       (end-of-line))
  2109.     (setq command (ex-expand-filsyms command (current-buffer)))
  2110.     (if (and (> (length command) 0) (string= "!" (substring command 0 1)))
  2111.     (if viper-ex-last-shell-com
  2112.         (setq command
  2113.           (concat viper-ex-last-shell-com (substring command 1)))
  2114.       (error "No previous shell command")))
  2115.     (setq viper-ex-last-shell-com command)
  2116.     (if (null ex-addresses)
  2117.     (shell-command command)
  2118.       (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
  2119.     (if (null beg) (setq beg end))
  2120.     (save-excursion
  2121.       (goto-char beg)
  2122.       (set-mark end)
  2123.       (viper-enlarge-region (point) (mark t))
  2124.       (shell-command-on-region (point) (mark t) command t))
  2125.     (goto-char beg)))))
  2126.  
  2127. ;; Print line number
  2128. (defun ex-line-no ()
  2129.   (message "%d"
  2130.        (1+ (count-lines
  2131.         (point-min)
  2132.         (if (null ex-addresses) (point-max) (car ex-addresses))))))
  2133.  
  2134. ;; Give information on the file visited by the current buffer
  2135. (defun viper-info-on-file ()
  2136.   (interactive)
  2137.   (let ((pos1 (viper-line-pos 'start))
  2138.     (pos2 (viper-line-pos 'end))
  2139.     lines file info)
  2140.     (setq lines (count-lines (point-min) (viper-line-pos 'end))
  2141.       file (if (buffer-file-name)
  2142.            (concat (viper-abbreviate-file-name (buffer-file-name)) ":")
  2143.          (concat (buffer-name) " [Not visiting any file]:"))
  2144.       info (format "line=%d/%d pos=%d/%d col=%d %s"
  2145.                (if (= pos1 pos2)
  2146.                (1+ lines)
  2147.              lines)
  2148.                (count-lines (point-min) (point-max))
  2149.                (point) (1- (point-max))
  2150.                (1+ (current-column))
  2151.                (if (buffer-modified-p) "[Modified]" "[Unchanged]")))
  2152.     (if (< (+ 1 (length info) (length file))
  2153.        (window-width (minibuffer-window)))
  2154.     (message (concat file " " info))
  2155.       (save-window-excursion
  2156.     (with-output-to-temp-buffer " *viper-info*"
  2157.       (princ (concat "\n" file "\n\n\t" info "\n\n")))
  2158.     (let ((inhibit-quit t))
  2159.       (viper-set-unread-command-events (viper-read-event)))
  2160.     (kill-buffer " *viper-info*")))
  2161.     ))
  2162.  
  2163. ;; display all variables set through :set
  2164. (defun ex-show-vars ()
  2165.   (with-output-to-temp-buffer " *viper-info*"
  2166.     (princ (if viper-auto-indent
  2167.            "autoindent (local)\n" "noautoindent (local)\n"))
  2168.     (princ (if (default-value 'viper-auto-indent) 
  2169.            "autoindent (global) \n" "noautoindent (global) \n"))
  2170.     (princ (if viper-case-fold-search "ignorecase\n" "noignorecase\n"))
  2171.     (princ (if viper-re-search "magic\n" "nomagic\n"))
  2172.     (princ (if buffer-read-only "readonly\n" "noreadonly\n"))
  2173.     (princ (if blink-matching-paren "showmatch\n" "noshowmatch\n"))
  2174.     (princ (if viper-search-wrap-around-t "wrapscan\n" "nowrapscan\n"))
  2175.     (princ (format "shiftwidth \t\t= %S\n" viper-shift-width))
  2176.     (princ (format "tabstop (local) \t= %S\n" tab-width))
  2177.     (princ (format "tabstop (global) \t= %S\n" (default-value 'tab-width)))
  2178.     (princ (format "wrapmargin (local) \t= %S\n"
  2179.            (- (window-width) fill-column)))
  2180.     (princ (format "wrapmargin (global) \t= %S\n"
  2181.            (- (window-width) (default-value 'fill-column))))
  2182.     (princ (format "shell \t\t\t= %S\n" (if (boundp 'explicit-shell-file-name)
  2183.                         explicit-shell-file-name
  2184.                       'none)))
  2185.     ))
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191. ;;;  viper-ex.el ends here
  2192.